package org.yuanqiframework.yuanqi.web.advice;


import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.yuanqiframework.yuanqi.web.auth.exception.ForbiddenException;
import org.yuanqiframework.yuanqi.web.auth.exception.UnauthorizedException;
import org.yuanqiframework.yuanqi.web.entity.AjaxResult;
import org.yuanqiframework.yuanqi.web.entity.ResponseCode;
import org.yuanqiframework.yuanqi.web.exception.BusinessException;
import org.yuanqiframework.yuanqi.web.exception.SystemException;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.List;

/**
 * 全局异常处理器
 *
 * @author 曹波涛
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @PostConstruct
    private void init() {
        log.info("Inject GlobalExceptionHandler");
    }


    /**
     * 未认证异常
     *
     * @return
     */
    @ExceptionHandler(UnauthorizedException.class)
    public AjaxResult<?> handleUnauthorizedException(UnauthorizedException e) {
        return AjaxResult.error(e.getMessage(), ResponseCode.UNAUTHORIZED);
    }

    /**
     * 权限不足异常
     *
     * @return
     */
    @ExceptionHandler(ForbiddenException.class)
    public AjaxResult<?> handleForbiddenException(ForbiddenException e) {
        return AjaxResult.error(e.getMessage(), ResponseCode.FORBIDDEN);
    }


    /**
     * RuntimeException
     *
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public AjaxResult<?> handleRuntimeException(RuntimeException e) {
        //记录到日志
        e.printStackTrace();
        log.error("{}\n{}", e.getMessage(), e.getStackTrace());
        return AjaxResult.error("系统错误", ResponseCode.ERROR, e.getMessage());
    }


    /**
     * 系统异常
     *
     * @return
     */
    @ExceptionHandler(SystemException.class)
    public AjaxResult<?> handleSystemException(SystemException e) {
        e.printStackTrace();
        log.error("{}\n{}", e.getMessage(), e.getStackTrace());
        return AjaxResult.error(e.getMessage(), e.getErrorCode(), e.getMessage());
    }

    /**
     * 业务异常
     *
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    public AjaxResult<?> handleBusinessException(BusinessException e) {
        e.printStackTrace();
        log.error("{}\n{}", e.getMessage(), e.getStackTrace());
        return AjaxResult.error(e.getMessage(), e.getErrorCode(), e.getErrorMessage());
    }

    /**
     * SQL异常
     *
     * @return
     */
    @ExceptionHandler(SQLException.class)
    public AjaxResult<?> handleSqlException(SQLException e) {
        e.printStackTrace();
        log.error("{}\n{}", e.getMessage(), e.getStackTrace());
        return AjaxResult.error("数据异常", e.getErrorCode(), e.getMessage());

    }

    /**
     * 请求方式不支持异常
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public AjaxResult<?> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e,
                                                                   HttpServletRequest request) {
        log.warn("请求地址'{}',不支持'{}'请求", request.getRequestURI(), e.getMethod());
        return AjaxResult.error("接口不支持" + e.getMethod() + "请求方式");
    }

    /**
     * 参数缺失验证异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public AjaxResult<?> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.warn("缺少请求参数:{}", e.getMessage());
        return AjaxResult.error("缺少参数", ResponseCode.ERROR, e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public AjaxResult<?> handleBindException(BindException e) {
        e.printStackTrace();
        log.error("{}\n{}", e.getMessage(), e.getStackTrace());
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return AjaxResult.error(message, ResponseCode.ERROR, e.getMessage());

    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public AjaxResult<?> handleMethodArgumentNotValidExceptionException(MethodArgumentNotValidException e) {
        e.printStackTrace();
        log.error("{}\n{}", e.getMessage(), e.getStackTrace());
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        FieldError error = fieldErrors.get(0);
        String message = error.getDefaultMessage();
        return AjaxResult.error(message, ResponseCode.ERROR, e.getMessage());
    }
}
